package com.zen.lon.open.remote.utils;

import com.zen.lon.open.remote.exp.RemoteClientException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import org.springframework.util.ClassUtils;

/**
 * @author ZonLen since on 2021/7/18 下午1:37
 */
public final class ClassProviderUtils {

  /**
   * 获取application入口main的包路径
   */
  public static String deduceMainApplicationClass() {
    StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
    for (StackTraceElement stackTraceElement : stackTrace) {
      if ("main".equals(stackTraceElement.getMethodName())) {
        final String className = stackTraceElement.getClassName();
        return ClassUtils.getPackageName(className);
      }
    }
    throw new RemoteClientException("This is not main run application");
  }

  public static Class<?> forName(String className) {
    try {
      return Class.forName(className);
    } catch (ClassNotFoundException e) {
      throw new RemoteClientException("class【" + className + "】 init forName exp");
    }
  }

  private static final Map<Class<?>, Map<Method, String>> FUNCTION_KEY = new ConcurrentHashMap<>();

  public static String functionFlag(Class<?> clazz, Method method) {
    if (FUNCTION_KEY.containsKey(clazz) && FUNCTION_KEY.get(clazz).containsKey(method)) {
      return FUNCTION_KEY.get(clazz).get(method);
    }
    final Map<Method, String> methodFlagMap = new ConcurrentHashMap<>();
    final String paramsType = Arrays.stream(method.getParameterTypes()).map(Class::getName)
        .collect(Collectors.joining(","));
    final Class<?> returnType = method.getReturnType();
    final String functionFlag = clazz.getName() + "." + method.getName()
        + "(" + paramsType + ")[" + returnType.getName() + "]";
    methodFlagMap.put(method, functionFlag);
    FUNCTION_KEY.put(clazz, methodFlagMap);
    return functionFlag;
  }


}
